﻿using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using System;

namespace FSMStateMachine
{
    public class UnityMonoStateHelper : MonoBehaviour
    {
        public static UnityMonoStateHelper instance;

        //Update事件执行的时间间隔(负数或0表示使用默认的Time.deltaTime)
        public float deltaTime = -1;
        /// <summary>
        /// update事件管理器
        /// </summary>
        [Obsolete("为解决传参问题，过时此事件", true)]
        public System.Action<State> runStateUpdate;
        /// <summary>
        /// update时间执行参数
        /// </summary>
        [Obsolete("为解决传参问题，过时此参数", true)]
        public State runStateParamter;
        /// <summary>
        /// 状态更新事件管理器
        /// </summary>
        public Dictionary<State, Action<State>> stateUpdate;

        public Action<State>[] cacheStateUpdateEvent;
        public State[] cacheStateUpdateParameter;

        private void Awake()
        {
            instance = this;
            stateUpdate = new Dictionary<State,Action<State>>();
        }

        IEnumerator Start()
        {
            while (true)
            {
                if (deltaTime <= 0)
                {
                    yield return new WaitForEndOfFrame(); 
                }
                else
                {
                    yield return new WaitForSeconds(deltaTime);
                }

                if(stateUpdate.Count != 0)
                {
                    //动态数组遍历无效异常
                    //InvalidOperationException: out of sync
                    //foreach (var item in stateUpdate)
                    //{
                    //    item.Value(item.Key);
                    //}

                    //解决动态数组遍历无效异常
                    if(cacheStateUpdateEvent == null || cacheStateUpdateEvent.Length != stateUpdate.Count)
                    {
                        cacheStateUpdateParameter = new State[stateUpdate.Keys.Count];
                        cacheStateUpdateEvent = new Action<State>[stateUpdate.Values.Count];
                    }

                    stateUpdate.Keys.CopyTo(cacheStateUpdateParameter, 0);
                    stateUpdate.Values.CopyTo(cacheStateUpdateEvent, 0);
                    for (int i = 0; i < cacheStateUpdateEvent.Length; i++)
                    {
                        cacheStateUpdateEvent[i](cacheStateUpdateParameter[i]);
                    }
                }
            }
        }
    }
}